home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 November: Tool Chest / Dev.CD Nov 00 TC Disk 1.toast / Sample Code / Archive / Interapplication Comm / AEObject-Edition Sample / Publish.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-09-28  |  35.9 KB  |  901 lines  |  [TEXT/MPS ]

  1. /*------------------------------------------------------------------------------
  2.  *
  3.  *  Apple Developer Technical Support
  4.  *
  5.  *  Edition publishing routines
  6.  *
  7.  *  Program:    AEObject-Edition Sample
  8.  *  File:       Publish.c - C Source
  9.  *
  10.  *  by:         C.K. Haun <TR>
  11.  *
  12.  *  Copyright © 1990-1992 Apple Computer, Inc.
  13.  *  All rights reserved.
  14.  *
  15.  *------------------------------------------------------------------------------
  16.  * Publish handles most of the publishing housekeeping.  There is (are,am,be,whatever) 
  17.  * some routines that are common to both publishing and subscribing, they 
  18.  * are located in Subscribe.c 
  19.  *----------------------------------------------------------------------------*/
  20. #define __PUBLISH__
  21.  
  22. #pragma segment Publish
  23.  
  24.  
  25. #include "Sampdefines.h"
  26.  
  27.  
  28. /*  CreatePublisher takes the currently selected area in the current window 
  29. *       and creates an edition.  It starts by setting up some default data 
  30. *       structures and creating a preview picture.  
  31. *       Then the user is prompted for a location and name for the publisher
  32. *       with the NewPublisherDialog.  If the user clicks OK, then the edition
  33. *       is created and the section handle and rectangle for this edition is
  34. *       stored in my data structure for this window, and the first edition
  35. *       is written out.
  36. */
  37.  
  38. OSErr CreatePublisher(OSType typeToMake,Boolean fromEvent,FSSpecPtr theSpec)
  39. {
  40.  
  41.     NewPublisherReply myreply;
  42.     Handle theData;
  43.     Rect currentRect;
  44.     mySectionDataHandle pubText;
  45.     Str31 addPub;
  46.     static pubCounter;
  47.     OSErr myErr;
  48.     FSSpecPtr theOwningDoc = nil;
  49.     FSSpec tempSpec;
  50.     windowCHandle shortName;
  51.     extern Point expPoint;
  52.     extern Boolean gExpanded;
  53.     Boolean myWasChanged;
  54.     /* we're publishing from the current, topmost window */
  55.     shortName = (windowCHandle)GetWRefCon(FrontWindow());
  56.     HLock((Handle)shortName);
  57.     switch (typeToMake) {
  58.         case kGenericPICTWord:
  59.             currentRect = (*shortName)->selectionRect;
  60.             /* take the rectangle we currently have selected, and make it a picture */
  61.             theData = (Handle)MyMakePicture(¤tRect);      /* my function to make a PICT */
  62.             /* Set up the reply record for the publisher dialog.  */
  63.             myreply.usePart = false;                        /* must be false */
  64.             myreply.previewFormat = kGenericPICTWord;                 /* type of data we're publishing */
  65.             myreply.preview = theData;                      /* handle to the pict data */
  66.             break;
  67.         case kGenericTEXTWord:
  68.             /* make text preview */
  69.             myreply.usePart = false;                        /* must be false */
  70.             myreply.previewFormat = kGenericTEXTWord;                 /* type of data we're publishing */
  71.             pubText = GetTextSection(shortName, stPublisher);
  72.             HLock((Handle)pubText);
  73.             theData = (*pubText)->additionalData;                  /* duplicate the text for our preview */
  74.             HandToHand(&theData);
  75.             if (GetHandleSize(theData) > kMaxTextPreview)
  76.                 SetHandleSize(theData, kMaxTextPreview);
  77.             
  78.             myreply.preview = theData;
  79.             break;
  80.         case kCustomType:
  81.             break;
  82.     }
  83.     GetLastEditionContainerUsed(&gEdSpec);                  /* get a new edition containter.  */
  84.     /* this call gives us a duplicate of the last used, or if none used last, gives */
  85.     /* us a default container */
  86.     /* BY THE WAY - the 'last used' means the last used by the Edition Manager, not */
  87.     /* by your application, so if you don't specify a default name then the */
  88.     /* name that comes up as the default for the edition may be the last */
  89.     /* name used by another application, or from the last time your */
  90.     /* application was run.  So if you are concerned about this (like you */
  91.     /* think it may confuse the user) set your own default */
  92.     /* As a sidelight (and not guarenteed) an alias to the last edition container used */
  93.     /* is stored in the 'Preferences' folder in the system folder */
  94.     myreply.container = gEdSpec;                            /* put our file spec in the container to be filled */
  95.     /* now set the default name to be the same as the window plus a count */
  96.     GetWTitle(FrontWindow(), &myreply.container.theFile.name);
  97.     GetIndString(addPub, kGeneralStrings, kDotPub);
  98.     AppendString(myreply.container.theFile.name, addPub);
  99.     NumToString((long)((*shortName)->numPubs) + 1, addPub);
  100.     AppendString(myreply.container.theFile.name, addPub);
  101.     if(!fromEvent){
  102.     if (!gExpanded)
  103.         myErr = NewPublisherDialog(&myreply);               /* run the dialog */
  104.     else
  105.     {
  106.         ExpDlgHookUPP dhUPP = NewExpDlgHookProc(ExpOptHook);
  107.         ExpModalFilterUPP mfUPP = NewExpModalFilterProc(ExpOptFilter);
  108.         myErr = NewPublisherExpDialog(&myreply, expPoint, kExpandedDITL, dhUPP, mfUPP, nil);
  109.         DisposeRoutineDescriptor(dhUPP);
  110.         DisposeRoutineDescriptor(mfUPP);
  111.     }
  112.     
  113.     if (myErr) {
  114.         ShowMe("\pPubisher dialog", myErr,__LINE__);
  115.         return(myErr);
  116.     }
  117.     if (myreply.canceled) {                                 /* they canceled.  release memory, reset our */
  118.         /* menus and cursors, and go away */
  119.         switch (typeToMake) {
  120.             case kGenericPICTWord:
  121.                 KillPicture((PicHandle)theData);
  122.                 InvalRect(&(*shortName)->selectionRect);
  123.                 gShowPub = false;
  124.                 (*shortName)->hasSelection = false;
  125.                 SetMyCursor(0);
  126.                 SwitchChecks(kSelectStuff);
  127.                 
  128.                 break;
  129.             case kGenericTEXTWord:
  130.                 DisposeHandle((*pubText)->additionalData);
  131.                 DisposeHandle((Handle)pubText);
  132.                 DisposeHandle(theData);
  133.                 break;
  134.             case kCustomType:
  135.                 break;
  136.         }
  137.         return(userCanceledErr);
  138.     }}
  139.     /* They clicked Publish.  First create the container (file) to hold the data */
  140.     /* See if thye are replacing a file */
  141.     if (!myreply.replacing) {
  142.         /* If we were given a spec by the event, the put that file in */
  143.         if(theSpec)myreply.container.theFile=*theSpec;
  144.         if (myErr = CreateEditionContainerFile(&myreply.container.theFile, kMySignature, myreply.container.theFileScript)) {
  145.             ShowMe("\pCreateEditionContainerFIle", myErr,__LINE__);
  146.             return(myErr);
  147.         } 
  148.         } else {
  149.         /* they agreed to delete an existing file.  Kill it. */
  150.         FSpDelete(&myreply.container.theFile);
  151.         if (myErr = CreateEditionContainerFile(&myreply.container.theFile, kMySignature, myreply.container.theFileScript)) {
  152.             ShowMe("\pCreateEditionContainerFIle", myErr,__LINE__);
  153.             return(myErr);
  154.  
  155.         }
  156.     }
  157.     /* now create the section record to describe this data to the edition manager */
  158.     /*  The section handle that is returned by this function will be the */
  159.     /* way that you will reference this edition for as long as the edition is */
  160.     /* active. */
  161.     /* The main way you'll keep track is through the section ID number. */
  162.     /* In this case, I have a base ID number for the window, and I just increment */
  163.     /* my general ID (gSectionID) every time I create an edition, and add it to the window ID.  */
  164.     if (GetHandleSize((Handle)(*shortName)->fileAliasHandle) == 0) {
  165.         myErr = NewSection(&myreply.container, nil, stPublisher, (*shortName)->windowID + gSectionID, pumOnSave, &gSecHandle);
  166.         /* nil for sectionDocument if it's never been saved */
  167.     } else {
  168.         /* if the file has been saved once, then we can store a reference to the 'parent' file */
  169.         /* in the edition */
  170.  
  171.  
  172.         myErr = ResolveAlias(nil, ((*shortName)->fileAliasHandle), &tempSpec, &myWasChanged);
  173.         myErr = NewSection(&myreply.container, &tempSpec, stPublisher, (*shortName)->windowID + gSectionID, pumOnSave,
  174.                            &gSecHandle);
  175.         theOwningDoc=&tempSpec;
  176.     }
  177.         if (!myErr) {
  178.         /* put the section handle into our window structure */
  179.         (*gSecHandle)->refCon = kNeverSaved;                /*            meaning that this _document_ has not been saved */
  180.         /* put what type of thing this is in the refcon of the section handle */
  181.         switch (typeToMake) {
  182.             /* This is a little kludgy because I want to */
  183.             case kGenericPICTWord:
  184.                 (*gSecHandle)->refCon = kPictType;
  185.                 break;
  186.             case kGenericTEXTWord:
  187.                 (*gSecHandle)->refCon = kTextType;
  188.                 break;
  189.         }
  190.         StorePublisher(shortName, gSecHandle, &(*shortName)->selectionRect, pubText, typeToMake);
  191.     
  192.     /* now write the data to the container */
  193.     /* first make a spec from the saved alias, if there is one */
  194.     MyWriteSection(gSecHandle, theData, typeToMake,theOwningDoc);
  195.      } else {
  196.         /* error creating the section */
  197.         ShowMe("\p Couldn't create section", myErr,__LINE__);    
  198.     }
  199.     HUnlock(theData);
  200.     switch (typeToMake) {
  201.         case kGenericPICTWord:
  202.             KillPicture((PicHandle)theData);
  203.             break;
  204.         case kGenericTEXTWord:
  205.             break;
  206.         case kCustomType:
  207.             break;
  208.     }
  209.    
  210.     (*shortName)->hasSelection = false;
  211.     InvalRect(&(*shortName)->selectionRect);                /* get rid of border once publish has happened */
  212.     gShowPub = false;
  213.     (*shortName)->hasSelection = false;
  214.     SetMyCursor(0);
  215.     SwitchChecks(kSelectStuff);
  216.     HUnlock((Handle)shortName);
  217. }
  218.  
  219. /* end CreatePublisher */
  220.  
  221. /* MyUpdateEdition publishes the latest data for this edition.  This will
  222. * be called when the user selects 'Send Edition Now' from the options
  223. * dialog, or when the document is saved (if automatic saving is 
  224. * enabled), or if a section write AppleEvent happens
  225. */
  226. OSErr MyUpdateEdition(SectionHandle theSection)
  227. {
  228.     WindowPtr tempWindow;
  229.     Boolean tempSub, tempPub;
  230.     Boolean wasChanged;
  231.     windowCHandle shortName;
  232.     SectionHandle *tempPtr;
  233.     FSSpecPtr theOwningDoc=nil;
  234.     FSSpec owner;
  235.     register qq;
  236.     Rect *tempRectPtr;
  237.     extern Rect gShowPubRect;
  238.     extern Rect gShowSubRect;
  239.     WindowPtr owningWindow = FindSection(theSection);
  240.  
  241.     GetPort(&tempWindow);
  242.     shortName = (windowCHandle)GetWRefCon(owningWindow);
  243.     HLock((Handle)shortName);
  244.     if(GetHandleSize((Handle)(*shortName)->fileAliasHandle)){
  245.     ResolveAlias(nil,(*shortName)->fileAliasHandle,&owner,&wasChanged);
  246.     theOwningDoc=&owner;
  247.     }
  248.     if (((*theSection)->refCon & 0xf) == kPictType) {
  249.         HLock((Handle)theSection);
  250.         /* kill the borders, if any are showing right now */
  251.         tempSub = gShowSub;
  252.         tempPub = gShowPub;
  253.         if (gShowSub)
  254.             InvalRect(&gShowSubRect);
  255.         if (gShowPub)
  256.             InvalRect(&gShowPubRect);
  257.         gShowSub = gShowPub = false;
  258.         SetPort(owningWindow);
  259.         (ProcPtr)((*shortName)->drawMe)(shortName, owningWindow);     /* draw without borders */
  260.         /* 
  261.         /* search this window for the section asked for */
  262.         HLock((*shortName)->pubs);
  263.         tempPtr = (SectionHandle *)*(*shortName)->pubs;
  264.         for (qq = 0; qq < (*shortName)->numPubs; qq++) {
  265.             HLock((Handle)*tempPtr);
  266.             if ((*theSection)->sectionID == (*(*tempPtr))->sectionID) {
  267.                 PicHandle tempPic;
  268.                 /* it's this one, grab the rect, pic it, publish it, and go away */
  269.                 HLock((*shortName)->pubRects);
  270.                 tempRectPtr = (Rect *)*(*shortName)->pubRects;
  271.                 tempRectPtr += qq;
  272.                 tempPic = MyMakePicture(tempRectPtr);
  273.                 HUnlock((*shortName)->pubRects);
  274.                 MyWriteSection(*tempPtr, (Handle)tempPic, kGenericPICTWord,theOwningDoc);
  275.                 KillPicture(tempPic);
  276.                 HUnlock((Handle)*tempPtr);
  277.                 break;
  278.             }
  279.         }
  280.         HUnlock((Handle)theSection);
  281.         HUnlock((Handle)shortName);
  282.     } else {
  283.         mySectionDataHandle theTS = TextSectionFromSecHandle(theSection);
  284.         /* it's a text pub */
  285.         MyWriteSection(theSection, (*theTS)->additionalData, kGenericTEXTWord,theOwningDoc);
  286.         
  287.     }
  288.     InvalRect(&owningWindow->portRect);
  289.     SetPort(tempWindow);
  290.     return(noErr);
  291. }
  292.  
  293. /* end MyUpdateEdition */
  294.  
  295. /* MyMakePicture is a handy place to create our PICT demo data item.
  296. * It's called to create the actual edition data as well as the 'preview'
  297. * picture.
  298. */
  299. PicHandle MyMakePicture(Rect *thisRect)
  300. {
  301.     PicHandle thepic;
  302.     windowCHandle drawers;
  303.     Boolean tempPub, tempSub;
  304.     RgnHandle tempClip;
  305.     /* make sure borders aren't included in the picture */
  306.     tempPub = gShowPub;
  307.     tempSub = gShowSub;
  308.     gShowPub = false;
  309.     gShowSub = false;
  310.     tempClip = NewRgn();
  311.     GetClip(tempClip);
  312.     ClipRect(thisRect);
  313.     thepic = OpenPicture(thisRect);
  314.     drawers = (windowCHandle)GetWRefCon(FrontWindow() );
  315.     HLock((Handle)drawers);
  316.     (ProcPtr)((*drawers)->drawMe)(drawers, FrontWindow() );
  317.     HUnlock((Handle)drawers);
  318.     ClosePicture();
  319.     SetClip(tempClip);
  320.     DisposeRgn(tempClip);
  321.     /* restore old border states */
  322.     gShowPub = tempPub;
  323.     gShowSub = tempSub;
  324.     return(thepic);
  325. }
  326.  
  327. /* end MyMakePicture */
  328.  
  329. /* AEWriteSectionHandler is the AppleEvent handler for section write
  330. * events.   It first pulls the SectionHandle out of the AppleEvent record,
  331. * then verifies that this is a registered section (still active, not canceled)
  332. * and then calls MyUpdateEdition to write the edition
  333. */
  334. pascal OSErr AEWriteSectionHandler(AppleEvent *messagein, AppleEvent *reply, long refIn)
  335. {
  336. #pragma unused (reply,refIn)
  337.     SectionHandle theSection;
  338.     OSErr myErr;
  339.     myErr = GetSectionHandleFromEvent(messagein, &theSection);
  340.  
  341.     if (myErr = IsRegisteredSection((SectionHandle)theSection)) {
  342.         ShowMe("\p Write IsRegisteredSection", myErr,__LINE__);
  343.         return(myErr);
  344.     }
  345.     MyUpdateEdition(theSection);
  346.     
  347. }
  348.  
  349. /* end AEWriteSectionHandler */
  350. /* ••••• REVISED!  This event has been revised since it's initial release */
  351. /* to reflect the final definition of this event, and the object that it accepts  */
  352. /* as a parameter */
  353. /* •••• NEW EVENT •••• */
  354. /* •• Please read the description and code in the Inside Mac vol VI chapters on */
  355. /* the Edition Manager and APpleEvents for a full description */
  356. /* AECreatePubHandler handles the new create publisher event */
  357.  
  358. pascal OSErr AECreatePubHandler(AppleEvent *messagein, AppleEvent *reply, long refIn)
  359. {
  360. #pragma unused (reply,refIn)
  361.  
  362. windowCHandle tempWC;
  363. OSErr myErr = noErr;
  364. Size returnedSize;
  365. long savedStart,savedEnd;
  366. Rect savedRect;
  367. DescType returnedType = typeNull;
  368. OSType theType;
  369. AEDesc returnedToken;
  370. AEDesc theObject;
  371. FSSpec theFSSpec;
  372. FSSpecPtr theFSS = nil;
  373. CTextObjHandle cTextBack;
  374. CWordObjHandle cWordBack;
  375. CShapeObjHandle cShapeback;
  376.  
  377. WindowPtr containingWindow;
  378. WindowPtr oldFront=nil;
  379. theObject.descriptorType = typeNull;
  380. returnedToken.descriptorType = typeNull;
  381. oldFront = FrontWindow();
  382. /* this event has two parameters, a object specifier and an alias handle. */
  383. /* Both parameters are optional. */
  384. /* if the object doesn't exsist, then we publish the current selection */
  385. /* if the alias doesn't exsist, then we put up the options dialog */
  386. AEGetParamDesc(messagein,keyDirectObject,typeObjectSpecifier,&theObject);
  387. /* the AEM has a built-in coercion from alias to FSSpec */
  388. AEGetParamPtr(messagein,keyAEEditionFileLoc,typeAlias,&returnedType,(Ptr)&theFSSpec,sizeof(FSSpec),&returnedSize);
  389. if(typeFSS == returnedType)
  390.     theFSS = &theFSSpec;
  391.  
  392. /* checking for null instead of for an error 
  393. because I don't care if either of these error out, I just care if they return a descriptor 
  394. or not.  Which I could do with two error variables, but you know.... */
  395. /* Now resolve the object I got (if I got one)  */
  396. if(theObject.descriptorType != typeNull) 
  397.     myErr = AEResolve(&theObject, kAEIDoMinimum, &returnedToken);
  398.  
  399. if(!myErr){
  400. /* so the action, will be something like this, since I am but a lowly  */
  401. /* example program */
  402. /* if the value returned from AEResolve is a graphic-type thing, I will put it's */
  403. /* rectangle into the current selection, and call CreatePub. */
  404. /* if it's a text thing, I will save the current selection, reset the selction, and */
  405. /* call CreatePub.  I'm typing this in as a comment because I don't know if I'll */
  406. /* get it implemented within my release timeframe, but that is the idea. */
  407. /* Also, because of the way I initially designed this program, the publisher must */
  408. /* be the front window.  Not a good idea, I will re-write that in a future release, */
  409. /* but for now we live with it. */
  410.     switch(returnedToken.descriptorType){
  411.     /* get the owning window */
  412.     case cText:
  413.     theType = kGenericTEXTWord;
  414.     cTextBack = (CTextObjHandle)returnedToken.dataHandle;
  415.     containingWindow=(*cTextBack)->theOwningWindow;
  416.     tempWC = (windowCHandle)GetWRefCon(containingWindow);
  417.     /* save off current  */
  418.     savedStart = (*(*tempWC)->boxHandle)->selStart;
  419.     savedEnd=(*(*tempWC)->boxHandle)->selEnd;
  420.     /* and since they asked for the whole text, make the end equal the beginning */
  421.     (*(*tempWC)->boxHandle)->selEnd = (*(*tempWC)->boxHandle)->teLength;
  422.     (*(*tempWC)->boxHandle)->selStart=0;
  423.     /* and do the thing */
  424.     SelectWindow(containingWindow);
  425.     
  426.     myErr = CreatePublisher(theType,true,theFSS);
  427.     /* restore */
  428.     (*(*tempWC)->boxHandle)->selStart = savedStart;
  429.     (*(*tempWC)->boxHandle)->selEnd = savedEnd;
  430.  
  431.  
  432.     break;
  433.     
  434.     case cWord:
  435.     theType = kGenericTEXTWord;
  436.     cWordBack = (CWordObjHandle)returnedToken.dataHandle;
  437.     containingWindow=(*cWordBack)->theOwningWindow;
  438.     tempWC = (windowCHandle)GetWRefCon(containingWindow);
  439.     savedStart = (*(*tempWC)->boxHandle)->selStart;
  440.     savedEnd=(*(*tempWC)->boxHandle)->selEnd;
  441.     (*(*tempWC)->boxHandle)->selStart = (*cWordBack)->startPos;
  442.     (*(*tempWC)->boxHandle)->selEnd = (*cWordBack)->endPos;
  443.     /* do the thing */
  444.     SelectWindow(containingWindow);
  445.  
  446.     myErr = CreatePublisher(theType,true,theFSS);
  447.     (*(*tempWC)->boxHandle)->selStart = savedStart;
  448.     (*(*tempWC)->boxHandle)->selEnd = savedEnd;
  449.     break;
  450.     case cGraphicLine:
  451.     case cRectangle:
  452.     case cOval:
  453.     theType = kGenericPICTWord;
  454.     /* save the current selection rect if any */
  455.     cShapeback = (CShapeObjHandle)returnedToken.dataHandle;
  456.     containingWindow=(*cShapeback)->theOwningWindow;
  457.     tempWC = (windowCHandle)GetWRefCon(containingWindow);
  458.     savedRect=(*tempWC)->selectionRect;
  459.     (*tempWC)->selectionRect = (*(*cShapeback)->theShape)->theRect;
  460.     SelectWindow(containingWindow);
  461.  
  462.     myErr = CreatePublisher(theType,true,theFSS);
  463.     (*tempWC)->selectionRect = savedRect; 
  464.     break;
  465.     default:
  466.     myErr = errAEEventNotHandled;    /* I don't know how to publish this object */
  467.     break;
  468.     }
  469. } else {
  470. /* Here, there was an object, but I couldn't understand it.  That is an _error_ */
  471. /* condition, which is different from no object being available */
  472.  
  473. myErr= errAENoSuchObject;
  474. }
  475.  
  476. /* if there was an old front window, make it frontmost agin */
  477. if(oldFront)ChangePlane(oldFront);
  478. return(myErr);
  479. }
  480. /* end AECreatePubHandler */
  481.  
  482.  
  483.  
  484. /* AEScrollSectionHandler handles the scroll section event.  You'll get this
  485. * event when the user clicks 'Open Publisher' either from the 
  486. * Subcriber Options dialog, or from the Finder window.
  487. * This may also have happened after an ODOC AppleEvent, so 
  488. * don't assume anything about your state that wouldn't be true 
  489. * after an initial application launch
  490. */
  491. pascal OSErr AEScrollSectionHandler(AppleEvent *messagein, AppleEvent *reply, long refIn)
  492. {
  493. #pragma unused (reply,refIn)
  494.     WindowPtr tempWindow;
  495.     SectionHandle theSection;
  496.     OSErr myErr;
  497.     myErr = GetSectionHandleFromEvent(messagein, &theSection);
  498.     tempWindow = FindSection(theSection);
  499.     /* First bring our application to the front, then */
  500.     /* treat this the same way you would a click in a back window */
  501.  
  502.     myErr=AEInteractWithUser(kAEDefaultTimeout,nil, gCommonIdleFunctionUPP);
  503.     if(!myErr)SetFrontProcess(&gOurSN);
  504.         else ShowMe("\ptheEr",myErr,__LINE__);
  505.     if (tempWindow != nil)
  506.         ChangePlane(tempWindow);
  507.     return(noErr);
  508. }
  509.  
  510. /* end AEScrollSectionHandler */
  511.  
  512. /* AECancelSectionHandler cancels a current section, either a publisher
  513. * or subscriber.  This function pulls the section handle out of the 
  514. * AppleEvent, then dispatches to the proper cancel routine for a
  515. * pub or sub.
  516. */
  517. pascal OSErr AECancelSectionHandler(AppleEvent *messagein, AppleEvent *reply, long refIn)
  518. {
  519. #pragma unused (reply,refIn)
  520.     SectionHandle theSection;
  521.     OSErr myErr;
  522.     myErr = GetSectionHandleFromEvent(messagein, &theSection);
  523.     myErr = IsRegisteredSection(theSection);
  524.     if (myErr != noErr)
  525.         return(myErr);                                      /* already killed by someone */
  526.     MyCancelSection(theSection, FindSection(theSection));
  527.     
  528. }
  529.  
  530. /* end AECancelSectionHandler */
  531.  
  532. /* MyWriteSection actually opens and writes the section data.  This will
  533. * be called in response to a click in 'Send Edition Now' in the pub options
  534. * box, from the section event 'write section', or when the file is being saved
  535. * and 'pumAuto' is enabled
  536. */
  537. OSErr MyWriteSection(SectionHandle secHandle, Handle theData, OSType theType,FSSpecPtr inSpec)
  538. {
  539.     OSErr myErr;
  540.     /* update the time in the section handle please */
  541.     /* this tells the Edition Manager that the eidtion has changed, and */
  542.     /* to alert all the subscribers to the change */
  543.  
  544.     SpinCursor();
  545.     HLock((Handle)secHandle);
  546.     GetDateTime(&(*secHandle)->mdDate);                     /* ••• Please see NOTE in main.c about mdDate (find mdDate) */
  547.     HUnlock((Handle)secHandle);
  548.     /* OpenNewEdition, _NOT_ OpenEdition.  You need to use OpenNewEdition */
  549.     /* to get write access and to let the Edition Manager determine if you */
  550.     /* are allowed to write to this section */
  551.     myErr = OpenNewEdition(secHandle, kMySignature,inSpec, &gEdRefNum);
  552.     if (myErr)
  553.         ShowMe("\pOpenNewEdition", myErr,__LINE__);
  554.     HLock(theData);
  555.     /* And actually write the data (finally) */
  556.     SpinCursor();
  557.     myErr = WriteEdition(gEdRefNum, theType, *theData, GetHandleSize(theData));
  558.     if (myErr)
  559.         ShowMe("\pWriteEdition", myErr,__LINE__);
  560.     if (myErr)
  561.         myErr = 0;
  562.     else
  563.         myErr = -1;
  564.     /* The Boolean tells the Edition Manager if you were successful in */
  565.     /* writing the data. */
  566.     myErr = CloseEdition(gEdRefNum, (Boolean)myErr);
  567.             if(myErr)ShowMe("\pCloseEdition", myErr,__LINE__);
  568.     return(myErr);
  569. }
  570.  
  571. /* end MyWriteSection */
  572.  
  573. /* StorePublisher moves the window data struct storing function to here */
  574. /* shortName is locked on entry */
  575. void StorePublisher(windowCHandle shortName, SectionHandle storeSection, Rect *inRect, mySectionDataHandle textIn, OSType typeIn)
  576. {
  577.     Rect *tempRectPtr;
  578.     SectionHandle *tempPtr;
  579.     OSErr myErr;
  580.     switch (typeIn) {
  581.         case kGenericPICTWord:
  582.             HUnlock((*shortName)->pubs);
  583.             MySetHandleSize((*shortName)->pubs, GetHandleSize((*shortName)->pubs) + sizeof(Handle));
  584.             myErr = MemError();
  585.             if (myErr)
  586.                 ShowMe("\pMemory", myErr,__LINE__);
  587.             HLock((*shortName)->pubs);
  588.             tempPtr = (SectionHandle *)((*(*shortName)->pubs) + (sizeof(Handle) * ((*shortName)->numPubs)));
  589.             *tempPtr = (SectionHandle)storeSection;
  590.             /* •••• NOTE, please look at the note in the Subscribe.c file concerning the dirty flag and  */
  591.             /* editions.  Open Subscribe.c and find the string 'Human Interface' */
  592.             /*    (*shortName)->windowDirty = true;  */
  593.             /* save the rectangle to show the published rectangle if the user wants to see it. */
  594.             HUnlock((*shortName)->pubRects);
  595.             MySetHandleSize((*shortName)->pubRects, (GetHandleSize((*shortName)->pubRects) + sizeof(Rect)));
  596.             myErr = MemError();
  597.             if (myErr)
  598.                 ShowMe("\pMemory", myErr,__LINE__);
  599.             HLock((*shortName)->pubRects);
  600.             tempRectPtr = (Rect *)*(*shortName)->pubRects;
  601.             tempRectPtr += (*shortName)->numPubs;
  602.             *tempRectPtr = *inRect;
  603.             (*shortName)->numPubs++;
  604.             HUnlock((*shortName)->pubRects);
  605.             HUnlock((*shortName)->pubs);
  606.             break;
  607.         case kGenericTEXTWord:
  608.             /* set my text section ID to the same as the actual section ID, again, it keeps */
  609.             /* dereferencing down */
  610.             (*textIn)->theID = (*storeSection)->sectionID;
  611.             /* tell myself that this is a publisher */
  612.             (*textIn)->publishing = true;
  613.             if ((*shortName)->textSections == nil) {
  614.                 (*shortName)->textSections = textIn;
  615.             } else {
  616.                 mySectionDataHandle tempTS = (*shortName)->textSections;
  617.                 while ((*tempTS)->nextSection != nil) {
  618.                     tempTS = (*tempTS)->nextSection;
  619.                 }
  620.                 (*tempTS)->nextSection = textIn;
  621.             }
  622.             (*textIn)->theSection = storeSection;
  623.             break;
  624.     }
  625.     gSectionID++;
  626. }
  627.  
  628. /* Find Section returns the window that this section is included in */
  629. /* Need to look in both the PICT and TEXT lists */
  630. WindowPtr FindSection(SectionHandle inSection)
  631. {
  632.      long subIDtofind;
  633.     Boolean secFound = false;
  634.     SectionHandle *tempPtr;
  635.     SectionRecord *tempRecord;
  636.     Handle tempHandle;
  637.     WindowPtr tempNextWindow;
  638.     register jj;
  639.     subIDtofind = (*inSection)->sectionID;
  640.     tempNextWindow = (WindowPtr)LMGetWindowList();  /* start at the beginning of the chain */
  641.     while(tempNextWindow){
  642.     if (((WindowPeek)tempNextWindow)->windowKind == kDocumentWindow){ /* the clipboard is not publishing */
  643.         windowCHandle tempWC;
  644.         /* do housekeeping to get to the section handle list */
  645.         tempWC = (windowCHandle)GetWRefCon(tempNextWindow);
  646.         HLock((Handle)tempWC);
  647.         if (((*inSection)->refCon & 0xf) == kPictType) {
  648.             tempHandle = (*tempWC)->pubs;                   /* handle containing SectionHandles */
  649.             HLock(tempHandle);
  650.             tempPtr = (SectionHandle *)*tempHandle;
  651.             /* Loop through all our sections until we find this edition */
  652.             for (jj = 0; jj < (*tempWC)->numPubs; jj++) {
  653.                 HLock((Handle)*tempPtr);
  654.                 tempRecord = *(*tempPtr);
  655.                 if (tempRecord->sectionID == subIDtofind) {
  656.                     HUnlock((Handle)*tempPtr);
  657.                     HUnlock((Handle)tempWC);
  658.                     return(tempNextWindow);
  659.                 } else {
  660.                     HUnlock((Handle)tempWC);
  661.                     HUnlock((Handle)*tempPtr);
  662.                     tempPtr += 1;
  663.                 }
  664.             }
  665.             HUnlock(tempHandle);
  666.             /* same thing for subscribers */
  667.             tempHandle = (*tempWC)->subs;                   /* handle containing SectionHandles */
  668.             HLock(tempHandle);
  669.             tempPtr = (SectionHandle *)*tempHandle;
  670.             /* Loop through all our sections until we find this edition */
  671.             for (jj = 0; jj < (*tempWC)->numSubs; jj++) {
  672.                 HLock((Handle)*tempPtr);
  673.                 tempRecord = *(*tempPtr);
  674.                 if (tempRecord->sectionID == subIDtofind) {
  675.                     HUnlock((Handle)*tempPtr);
  676.                     HUnlock((Handle)tempWC);
  677.                     return(tempNextWindow);
  678.                 } else {
  679.                     HUnlock((Handle)tempWC);
  680.                     HUnlock((Handle)*tempPtr);
  681.                     tempPtr += 1;
  682.                 }
  683.             }
  684.             HUnlock(tempHandle);
  685.         } else {
  686.             /* Look in the TEXT lists */
  687.             if ((*tempWC)->textSections) {
  688.                 mySectionDataHandle tempTS = (*tempWC)->textSections;
  689.                 do {
  690.                     if ((*((*tempTS)->theSection))->sectionID == subIDtofind) {
  691.                         HUnlock((Handle)tempWC);
  692.                         return(tempNextWindow);
  693.                     }
  694.                     tempTS = (*tempTS)->nextSection;
  695.                 } while (tempTS);
  696.                 
  697.             }
  698.         }
  699.         tempNextWindow = (WindowPtr)((WindowPeek)tempNextWindow)->nextWindow; 
  700.         
  701.         HUnlock((Handle)tempWC);
  702.         }    /* if document */
  703.         tempNextWindow = (WindowPtr) ((WindowPeek)tempNextWindow)->nextWindow;
  704.     } /* while windows */
  705.     return(nil);
  706. }
  707.  
  708. pascal short ExpOptHook(short itemOffset, short itemHit, DialogPtr theDialog, Ptr yourDataPtr)
  709. {
  710.  #pragma unused (yourDataPtr)
  711.      short myHit;
  712.     short itemType;
  713.     ControlHandle theButton;
  714.     Rect theRect;
  715.     /* first make sure that a sub-dialog is not frontmost */
  716.     /* so we don't filter keys or hits to a sub-dialog */
  717.     if (GetWRefCon((WindowPtr)theDialog) == sfMainDialogRefCon || GetWRefCon((WindowPtr)theDialog) == emOptionsDialogRefCon) {
  718.         /* only have one item in this expansion, but we'll check the range anyway */
  719.         myHit = itemHit - itemOffset;                       /* since our item numbers are relative to the total number */
  720.         /* of items in the dialog, and the system may change.  Always do your item numbering based */
  721.         /* on the offset, this will prevent incompatability when the system dialog grows or shrinks */
  722.         if (myHit == 1) {                                   /* I only added one item, so this be the one */
  723.             /* Pass itemHit here, not myHit, since the dialog manager has no idea that this is an */
  724.             /* additive dialog.  It is counting from the actual start of the DITL, not the start of */
  725.             /* your custom items */
  726.             GetDialogItem(theDialog, itemHit, &itemType, (Handle *)&theButton, &theRect);
  727.             if (GetControlValue(theButton))
  728.                 SetControlValue(theButton, false);
  729.             else
  730.                 SetControlValue(theButton, true);
  731.         }
  732.     }
  733.     return(itemHit);                                        /* the return value must be absolute */
  734. }
  735.  
  736. pascal Boolean ExpOptFilter(DialogPtr theDialog, EventRecord *theEvent, short itemOffset, short *itemHit, Ptr yourDataPtr)
  737. {
  738. #pragma unused (itemHit,yourDataPtr)
  739.     short itemType;
  740.     ControlHandle theButton;
  741.     Rect theRect;
  742.     /* first make sure that a sub-dialog is not frontmost */
  743.     /* so we don't filter keys or hits to a sub-dialog */
  744.     if (GetWRefCon((WindowPtr)theDialog) == sfMainDialogRefCon || GetWRefCon((WindowPtr)theDialog) == emOptionsDialogRefCon) {
  745.         /* standard filter proc kinda stuff here */
  746.         if ((theEvent->what) == keyDown) {
  747.             char tempChar;
  748.             tempChar = theEvent->message & charCodeMask;
  749.             
  750.             if (((tempChar == 'A') || (tempChar == 'a')) && (theEvent->modifiers & cmdKey)) {
  751.                 /* they pressed an A with the command key down, we get to handle it. */
  752.                 GetDialogItem(theDialog, itemOffset + 1, &itemType, (Handle *)&theButton, &theRect);
  753.                 if (GetControlValue(theButton))
  754.                     SetControlValue(theButton, false);
  755.                 else
  756.                     SetControlValue(theButton, true);
  757.                 
  758.                 return(true);                               /* tell folks we handled it */
  759.             }
  760.         }
  761.     }
  762.     return(false);                                          /* was not a keystroke we wanted */
  763.     
  764. }
  765.  
  766. /* shortName is locked on entry */
  767. mySectionDataHandle GetTextSection(windowCHandle shortName, SectionType what)
  768. {
  769.     CharsHandle theRawText;
  770.     TEHandle tempTE;
  771.     mySectionDataHandle theTextSection;
  772.     Handle theSelection;
  773.     theTextSection = (mySectionDataHandle)NewHandle(sizeof(mySectionData));
  774.     HLock((Handle)theTextSection);
  775.     (*theTextSection)->bordered = gShowingAll;              /* create section reflecting current */
  776.     /* global border state */
  777.     tempTE = (*shortName)->boxHandle;
  778.     (*theTextSection)->startChar = (*tempTE)->selStart;
  779.     if (what == stPublisher) {
  780.         /* initialize it if it's a publisher */
  781.         (*theTextSection)->endChar = (*tempTE)->selEnd;
  782.         
  783.         theRawText = TEGetText(tempTE);
  784.         theSelection = NewHandle(((*tempTE)->selEnd) - ((*tempTE)->selStart));
  785.         
  786.         HLock(theSelection);
  787.         HLock((Handle)theRawText);
  788.         BlockMove((Ptr)*theRawText + (*tempTE)->selStart, (Ptr)*theSelection, (*tempTE)->selEnd - (*tempTE)->selStart);
  789.         HUnlock(theSelection);
  790.         HUnlock((Handle)theRawText);
  791.         (*theTextSection)->additionalData = theSelection;
  792.     } else {
  793.         /* set start same as end for subscribers */
  794.         (*theTextSection)->endChar = (*tempTE)->selStart;
  795.         (*theTextSection)->additionalData = NewHandle(0);
  796.     }
  797.     (*theTextSection)->nextSection = nil;
  798.     return(theTextSection);
  799. }
  800.  
  801. mySectionDataHandle TextSectionFromSecHandle(SectionHandle theSection)
  802. {
  803.     windowCHandle tempWC = (windowCHandle)GetWRefCon(FindSection(theSection));      /* gets the window it's in */
  804.     mySectionDataHandle tempTS = (*tempWC)->textSections;
  805.     unsigned long idToFind;
  806.     
  807.     idToFind = (*theSection)->sectionID;
  808.     /* find the ID that matches this thang */
  809.     do {
  810.         if ((*tempTS)->theID == idToFind)
  811.             return(tempTS);
  812.         tempTS = (*tempTS)->nextSection;
  813.     } while (tempTS);
  814.     return(nil);                                            /* failed */
  815. }
  816.  
  817. /* In SearchPubs we'll search the publishers in this window for a publisher */
  818. /* that was clicked in.  If we find one, hilite it and outline it. */
  819. /* Point is already in local coordinates */
  820. Boolean SearchPubs(Point thePoint)
  821. {
  822.     register qq;
  823.     Rect rectToCheck;
  824.     Rect cornerRect;
  825.     Rect *theRects;
  826.     Str63 pubString;
  827.     Boolean gotIt = false;
  828.     windowCHandle shortname = (windowCHandle)GetWRefCon(FrontWindow());
  829.     HLock((Handle)shortname);
  830.     if ((*shortname)->numPubs) {                            /* does this window have any publishers? */
  831.         /* yes, see if one was clicked in */
  832.         HLock((*shortname)->pubRects);                      /* lock the rect handle down */
  833.         theRects = (Rect *)*(*shortname)->pubRects;
  834.         /* dereference it and cast it to a rect pointer so checking will be 
  835.         *   conceptually easier (i.e. you can read it) 
  836.         */
  837.         for (qq = 0; qq < (*shortname)->numPubs; qq++) {        /* step through 'em */
  838.             SectionHandle *tempPtr;
  839.             rectToCheck = *theRects;
  840.             if (PtInRect(thePoint, &rectToCheck)) {         /* thePoint is coming from your */
  841.                 /* last event record */
  842.                 /* We've found a section that has been clicked in */
  843.                 if (gShowPub && (rectToCheck != gShowPubRect))
  844.                     InvalRect(&gShowPubRect);               /* clear previous, if there was one */
  845.                 gShowPub = true;
  846.                 if (gShowSub) {/* clear previous, if there was one */
  847.                     InsetRect(&gShowSubRect, -4, -4);
  848.                     InvalRect(&gShowSubRect);
  849.                     InsetRect(&gShowSubRect, 4, 4);
  850.  
  851.                     gShowSub = false;
  852.                 }
  853.                 /* make sure the border gets draw next update */
  854.                 InsetRect(&rectToCheck,-4,-4);
  855.                 InvalRect(&rectToCheck);
  856.                 InsetRect(&rectToCheck,4,4);
  857.                 /* we've found it with it's rectangle, so now dig out the */
  858.                 /* section handle */
  859.                 HLock((*shortname)->pubs);
  860.                 tempPtr = (SectionHandle *)*(*shortname)->pubs;
  861.                 tempPtr += qq;
  862.                 /* and move the section handle into our global variable that */
  863.                 /* contains the currently highlighted section, so we can */
  864.                 /* access it from the Options function and dialog */
  865.                 gShowingSecHandle = *tempPtr;
  866.                 /* done with the pointer handle */
  867.                 HUnlock((*shortname)->pubs);
  868.                 /* change the menu item name now */
  869.                 GetIndString(pubString, kGeneralStrings, kPubOptString);
  870.                 
  871.                 SetMenuItemText(gEditMenuHandle, kSoptionsItem,pubString);
  872.                 gShowPubRect = rectToCheck;
  873.                 gotIt = true;
  874.                 /* Now we need to stretch the thing if the user wants too */
  875.                 /* See if it was in the corner rect first */
  876.                 cornerRect = gShowPubRect;
  877.                 cornerRect.top = cornerRect.bottom - 7;
  878.                 cornerRect.left = cornerRect.right - 7;
  879.                 if (PtInRect(thePoint, &cornerRect)) {
  880.                     PullRect(shortname, &gShowPubRect, false, true,true);
  881.                     if (*theRects != gShowPubRect) {
  882.                         *theRects = gShowPubRect;
  883.                         InvalRect(theRects);
  884.                     }
  885.                 }
  886.             }
  887.             if (gotIt)
  888.                 break;
  889.             theRects++;                                     /* increase by one Rect */
  890.         }
  891.         HUnlock((*shortname)->pubRects);
  892.     }
  893.     HUnlock((Handle)shortname);
  894.     return(gotIt);
  895. }
  896.  
  897. /* end SearchPubs */
  898.  
  899.  
  900. #undef __PUBLISH__
  901.